HUEL Satiety

Author

Guy Taylor

Published

April 17, 2024

1 Analysis of the Satiety Questionnaire

1.1 Load Libraries

Show the code
library(readxl)
library(tidyverse)
library(patchwork)
library(hrbrthemes)
library(DT)
library(knitr)
library(plotly)
library(tidyr)
library(dplyr)
library(car)
library(lme4)
library(lmerTest)
library(easystats)

1.2 Load Satiety Data

Data is displayed in wide format - each participant has a row - Column format is Intervention_Question_Time format (e.g. HUEL_S1_0 and Cornflakes_S6_180). I currently have not included AP009 as they pulled out, will discuss with Matt

Show the code
# Read the cleaned Satiety Study

Satiety <- read_excel("../Input/HUEL_satiety_input.xlsx")


#load function
source(file = "../R/HUEL_satiety_functions.R")

# Create an interactive table

datatable(Satiety, filter = "top")

Lets convert to long format - this won’t need repeating on the subsequent analysis

Show the code
# create a long format

Satiety_long <- Satiety %>%
    pivot_longer(cols = starts_with("HUEL_") | starts_with("Cornflakes_"), names_to = "Timepoint", values_to = "Measurement")

# Create Intervention column based on Timepoint
Satiety_long <- Satiety_long %>%
  mutate(Intervention = ifelse(str_detect(Timepoint, "^HUEL"), "HUEL", "Cornflakes"),
         Timepoint = gsub("^HUEL_|^Cornflakes_", "", Timepoint),
         Question = gsub("_.*", "", Timepoint),
         Timepoint = gsub("^S\\d+_", "", Timepoint))

2 Q1.

Question 1.

First subset the question:

Show the code
#Subset the question

S1_subset_data <- subset_data(Satiety_long, "S1")

Then mean +- SD and a graph:

Show the code
# create mean +- SD table for HUEL and Cornflakes S1, 0 to 240 minutes


result_S1 <- calculate_mean_sd(Satiety_long, question = "S1")

kable(result_S1)
Timepoint Mean_Cornflakes Mean_HUEL SD_Cornflakes SD_HUEL
0 62.3 60.5 20.0 21.9
15 26.3 21.5 22.4 21.4
30 31.1 18.7 26.1 17.2
45 31.6 21.4 24.1 19.4
60 34.7 24.3 24.0 19.9
90 37.8 28.9 22.5 21.8
120 45.2 34.9 23.2 22.6
150 52.5 40.3 22.3 23.4
180 60.0 51.0 21.7 25.0
210 65.5 56.3 20.0 25.6
240 72.4 63.8 18.2 22.0
Show the code
plot <- plot_mean_sd(result_S1)

print(plot)

2.1 2 Way ANOVA and Checking the assumptions

Then running functions to create and check a 2 way ANOVA (Intervention (HUEL or Cornflakes), Timepoint (0 to 240 minute) and Interaction (Intervention x Timepoint)) and a Mixed effects model (Intervention (HUEL or Cornflakes), Timepoint (0 to 240 minute) and Interaction (Intervention x Timepoint), with random effect of participant

Unsure whether to do in the mixed effects model:

(1 | participant) includes random intercepts for participants, capturing individual differences in baseline hunger levels. or (1 | participant:time) includes random intercepts for the interaction between participants and time, capturing variability in hunger ratings across different time points within each participant. .

Then a 2 way ANOVA and assumptions

Show the code
#| layout-ncol: 2

S1_anova_results_with_plots <- two_way_anova_with_plots(S1_subset_data)
Levene's Test for Homogeneity of Variance (center = median)
       Df F value Pr(>F)
group  21  1.1252 0.3146
      836               
NULL

                        Df Sum Sq Mean Sq F value   Pr(>F)    
Intervention             1  16945   16945  34.540 6.03e-09 ***
Timepoint               10 210890   21089  42.986  < 2e-16 ***
Intervention:Timepoint  10   1886     189   0.384    0.954    
Residuals              836 410144     491                     
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Independence of residuals: TRUE 

2.2 linear mixed model and assumptions

And let’s try linear mixed model instead where we account for participants, as well as assumptions

Show the code
S1_lmer_model <- lmer(Measurement ~ Timepoint * Intervention + (1|Participant), data = S1_subset_data)

anova(S1_lmer_model)
Type III Analysis of Variance Table with Satterthwaite's method
                       Sum Sq Mean Sq NumDF DenDF F value    Pr(>F)    
Timepoint              210890 21089.0    10   798  87.219 < 2.2e-16 ***
Intervention            16945 16945.2     1   798  70.081  2.54e-16 ***
Timepoint:Intervention   1886   188.6    10   798   0.780    0.6482    
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Show the code
check_model(S1_lmer_model)

Looks like the data will need to be transformed….

3 Q2.

Question 2.

First subset the question:

Show the code
#Subset the question

S2_subset_data <- subset_data(Satiety_long, "S2")

means and graph

Show the code
# create mean +- SD table for HUEL and Cornflakes S2, 0 to 240 minutes


result_S2 <- calculate_mean_sd(Satiety_long, question = "S2")

kable(result_S2)
Timepoint Mean_Cornflakes Mean_HUEL SD_Cornflakes SD_HUEL
0 26.2 21.7 21.4 15.2
15 63.4 69.3 27.2 26.2
30 64.0 69.6 24.4 25.1
45 62.5 71.9 24.7 21.0
60 58.1 70.5 24.7 21.7
90 51.7 64.5 24.5 21.7
120 48.3 59.0 24.4 22.8
150 40.9 53.7 22.7 21.8
180 38.2 46.6 22.6 24.0
210 30.1 40.8 22.1 24.3
240 28.4 36.5 23.9 23.3
Show the code
plot <- plot_mean_sd(result_S2)

print(plot)

3.1 2 Way ANOVA and Checking the assumptions

Then a 2 way ANOVA and assumptions

Show the code
#| layout-ncol: 2

S2_anova_results_with_plots <- two_way_anova_with_plots(S2_subset_data)
Levene's Test for Homogeneity of Variance (center = median)
       Df F value Pr(>F)
group  21  1.1758 0.2645
      836               
NULL

                        Df Sum Sq Mean Sq F value  Pr(>F)    
Intervention             1  15080   15080   27.82 1.7e-07 ***
Timepoint               10 186194   18619   34.35 < 2e-16 ***
Intervention:Timepoint  10   4826     483    0.89   0.542    
Residuals              836 453178     542                    
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Independence of residuals: TRUE 

3.2 linear mixed model and assumptions

And let’s try linear mixed model instead where we account for participants, as well as assumptions

Show the code
S2_lmer_model <- lmer(Measurement ~ Timepoint * Intervention + (1|Participant), data = S2_subset_data)

anova(S2_lmer_model)
Type III Analysis of Variance Table with Satterthwaite's method
                       Sum Sq Mean Sq NumDF DenDF F value    Pr(>F)    
Timepoint              186194 18619.4    10   798 54.3725 < 2.2e-16 ***
Intervention            15080 15079.7     1   798 44.0359 5.949e-11 ***
Timepoint:Intervention   4826   482.6    10   798  1.4093    0.1712    
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Show the code
check_model(S2_lmer_model)

4 Q3

Question 3.

First subset the question:

Show the code
#Subset the question

S3_subset_data <- subset_data(Satiety_long, "S3")

Then means and graph

Show the code
# create mean +- SD table for HUEL and Cornflakes S1, 0 to 240 minutes


result_S3 <- calculate_mean_sd(Satiety_long, question = "S3")

kable(result_S1)
Timepoint Mean_Cornflakes Mean_HUEL SD_Cornflakes SD_HUEL
0 62.3 60.5 20.0 21.9
15 26.3 21.5 22.4 21.4
30 31.1 18.7 26.1 17.2
45 31.6 21.4 24.1 19.4
60 34.7 24.3 24.0 19.9
90 37.8 28.9 22.5 21.8
120 45.2 34.9 23.2 22.6
150 52.5 40.3 22.3 23.4
180 60.0 51.0 21.7 25.0
210 65.5 56.3 20.0 25.6
240 72.4 63.8 18.2 22.0
Show the code
plot <- plot_mean_sd(result_S3)

print(plot)

4.1 2 Way ANOVA and Checking the assumptions

Then a 2 way ANOVA and assumptions

Show the code
#| layout-ncol: 2

S3_anova_results_with_plots <- two_way_anova_with_plots(S3_subset_data)
Levene's Test for Homogeneity of Variance (center = median)
       Df F value    Pr(>F)    
group  21  2.4863 0.0002463 ***
      836                      
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
NULL

                        Df Sum Sq Mean Sq F value   Pr(>F)    
Intervention             1  18741   18741  36.722 2.06e-09 ***
Timepoint               10 273983   27398  53.685  < 2e-16 ***
Intervention:Timepoint  10   2129     213   0.417    0.939    
Residuals              836 426658     510                     
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Independence of residuals: TRUE 

4.2 linear mixed model and assumptions

And let’s try linear mixed model instead where we account for participants, as well as assumptions

Show the code
S3_lmer_model <- lmer(Measurement ~ Timepoint * Intervention + (1|Participant), data = S3_subset_data)

anova(S3_lmer_model)
Type III Analysis of Variance Table with Satterthwaite's method
                       Sum Sq Mean Sq NumDF DenDF  F value    Pr(>F)    
Timepoint              273983 27398.3    10   798 101.8963 < 2.2e-16 ***
Intervention            18741 18741.4     1   798  69.7005 3.034e-16 ***
Timepoint:Intervention   2129   212.9    10   798   0.7918    0.6368    
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Show the code
check_model(S3_lmer_model)

5 Q4

Question 4.

First subset the question:

Show the code
#Subset the question

S4_subset_data <- subset_data(Satiety_long, "S4")

Mean and graph:

Show the code
# create mean +- SD table for HUEL and Cornflakes S1, 0 to 240 minutes


result_S4 <- calculate_mean_sd(Satiety_long, question = "S4")

kable(result_S1)
Timepoint Mean_Cornflakes Mean_HUEL SD_Cornflakes SD_HUEL
0 62.3 60.5 20.0 21.9
15 26.3 21.5 22.4 21.4
30 31.1 18.7 26.1 17.2
45 31.6 21.4 24.1 19.4
60 34.7 24.3 24.0 19.9
90 37.8 28.9 22.5 21.8
120 45.2 34.9 23.2 22.6
150 52.5 40.3 22.3 23.4
180 60.0 51.0 21.7 25.0
210 65.5 56.3 20.0 25.6
240 72.4 63.8 18.2 22.0
Show the code
plot <- plot_mean_sd(result_S4)

print(plot)

5.1 2 Way ANOVA and Checking the assumptions

Then a 2 way ANOVA and assumptions

Show the code
#| layout-ncol: 2

S4_anova_results_with_plots <- two_way_anova_with_plots(S4_subset_data)
Levene's Test for Homogeneity of Variance (center = median)
       Df F value Pr(>F)
group  21  0.7148 0.8206
      836               
NULL

                        Df Sum Sq Mean Sq F value   Pr(>F)    
Intervention             1  13025   13025  22.755 2.17e-06 ***
Timepoint               10 156857   15686  27.403  < 2e-16 ***
Intervention:Timepoint  10   1671     167   0.292    0.983    
Residuals              836 478532     572                     
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Independence of residuals: TRUE 

5.2 linear mixed model and assumptions

And let’s try linear mixed model instead where we account for participants, as well as assumptions

Show the code
S4_lmer_model <- lmer(Measurement ~ Timepoint * Intervention + (1|Participant), data = S4_subset_data)

anova(S4_lmer_model)
Type III Analysis of Variance Table with Satterthwaite's method
                       Sum Sq Mean Sq NumDF DenDF F value    Pr(>F)    
Timepoint              156857 15685.7    10   798 53.0928 < 2.2e-16 ***
Intervention            13025 13025.2     1   798 44.0878 5.802e-11 ***
Timepoint:Intervention   1671   167.1    10   798  0.5656    0.8426    
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Show the code
check_model(S4_lmer_model)

6 Q5

Question 5.

First subset the question:

Show the code
#Subset the question

S5_subset_data <- subset_data(Satiety_long, "S5")

Mean and graph

Show the code
# create mean +- SD table for HUEL and Cornflakes S1, 0 to 240 minutes


result_S5 <- calculate_mean_sd(Satiety_long, question = "S5")

kable(result_S1)
Timepoint Mean_Cornflakes Mean_HUEL SD_Cornflakes SD_HUEL
0 62.3 60.5 20.0 21.9
15 26.3 21.5 22.4 21.4
30 31.1 18.7 26.1 17.2
45 31.6 21.4 24.1 19.4
60 34.7 24.3 24.0 19.9
90 37.8 28.9 22.5 21.8
120 45.2 34.9 23.2 22.6
150 52.5 40.3 22.3 23.4
180 60.0 51.0 21.7 25.0
210 65.5 56.3 20.0 25.6
240 72.4 63.8 18.2 22.0
Show the code
plot <- plot_mean_sd(result_S5)

print(plot)

6.1 2 Way ANOVA and Checking the assumptions

Then a 2 way ANOVA and assumptions

Show the code
#| layout-ncol: 2

S5_anova_results_with_plots <- two_way_anova_with_plots(S5_subset_data)
Levene's Test for Homogeneity of Variance (center = median)
       Df F value Pr(>F)
group  21   0.756  0.775
      836               
NULL

                        Df Sum Sq Mean Sq F value   Pr(>F)    
Intervention             1  11208   11208  16.636 4.96e-05 ***
Timepoint               10  41226    4123   6.119 4.83e-09 ***
Intervention:Timepoint  10   1747     175   0.259    0.989    
Residuals              836 563216     674                     
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Independence of residuals: TRUE 

6.2 linear mixed model and assumptions

And let’s try linear mixed model instead where we account for participants, as well as assumptions

Show the code
S5_lmer_model <- lmer(Measurement ~ Timepoint * Intervention + (1|Participant), data = S5_subset_data)

anova(S5_lmer_model)
Type III Analysis of Variance Table with Satterthwaite's method
                       Sum Sq Mean Sq NumDF DenDF F value    Pr(>F)    
Timepoint               41226  4122.6    10   798 14.7259 < 2.2e-16 ***
Intervention            11208 11207.7     1   798 40.0336 4.158e-10 ***
Timepoint:Intervention   1747   174.7    10   798  0.6239    0.7942    
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Show the code
check_model(S5_lmer_model)

7 Q6

Question 6.

Show the code
# create mean +- SD table for HUEL and Cornflakes S1, 0 to 240 minutes


result_S6 <- calculate_mean_sd(Satiety_long, question = "S6")

kable(result_S1)
Timepoint Mean_Cornflakes Mean_HUEL SD_Cornflakes SD_HUEL
0 62.3 60.5 20.0 21.9
15 26.3 21.5 22.4 21.4
30 31.1 18.7 26.1 17.2
45 31.6 21.4 24.1 19.4
60 34.7 24.3 24.0 19.9
90 37.8 28.9 22.5 21.8
120 45.2 34.9 23.2 22.6
150 52.5 40.3 22.3 23.4
180 60.0 51.0 21.7 25.0
210 65.5 56.3 20.0 25.6
240 72.4 63.8 18.2 22.0
Show the code
plot <- plot_mean_sd(result_S6)

print(plot)

First subset the question:

Show the code
#Subset the question

S6_subset_data <- subset_data(Satiety_long, "S6")

7.1 2 Way ANOVA and Checking the assumptions

Then a 2 way ANOVA and assumptions

Show the code
#| layout-ncol: 2

S6_anova_results_with_plots <- two_way_anova_with_plots(S6_subset_data)
Levene's Test for Homogeneity of Variance (center = median)
       Df F value Pr(>F)
group  21  0.4653 0.9811
      836               
NULL

                        Df Sum Sq Mean Sq F value   Pr(>F)    
Intervention             1   1312    1312   1.737    0.188    
Timepoint               10  58479    5848   7.743 6.21e-12 ***
Intervention:Timepoint  10   1099     110   0.146    0.999    
Residuals              836 631380     755                     
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Independence of residuals: TRUE 

7.2 linear mixed model and assumptions

And let’s try linear mixed model instead where we account for participants, as well as assumptions

Show the code
S6_lmer_model <- lmer(Measurement ~ Timepoint * Intervention + (1|Participant), data = S6_subset_data)

anova(S6_lmer_model)
Type III Analysis of Variance Table with Satterthwaite's method
                       Sum Sq Mean Sq NumDF DenDF F value  Pr(>F)    
Timepoint               58479  5847.9    10   798 17.4081 < 2e-16 ***
Intervention             1312  1312.0     1   798  3.9056 0.04847 *  
Timepoint:Intervention   1099   109.9    10   798  0.3272 0.97399    
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Show the code
check_model(S6_lmer_model)

8 Q7

Question 7.

Show the code
# create mean +- SD table for HUEL and Cornflakes S1, 0 to 240 minutes


result_S7 <- calculate_mean_sd(Satiety_long, question = "S7")

kable(result_S1)
Timepoint Mean_Cornflakes Mean_HUEL SD_Cornflakes SD_HUEL
0 62.3 60.5 20.0 21.9
15 26.3 21.5 22.4 21.4
30 31.1 18.7 26.1 17.2
45 31.6 21.4 24.1 19.4
60 34.7 24.3 24.0 19.9
90 37.8 28.9 22.5 21.8
120 45.2 34.9 23.2 22.6
150 52.5 40.3 22.3 23.4
180 60.0 51.0 21.7 25.0
210 65.5 56.3 20.0 25.6
240 72.4 63.8 18.2 22.0
Show the code
plot <- plot_mean_sd(result_S7)

print(plot)

First subset the question:

Show the code
#Subset the question

S7_subset_data <- subset_data(Satiety_long, "S7")

8.1 2 Way ANOVA and Checking the assumptions

Then a 2 way ANOVA and assumptions

Show the code
#| layout-ncol: 2

S7_anova_results_with_plots <- two_way_anova_with_plots(S7_subset_data)
Levene's Test for Homogeneity of Variance (center = median)
       Df F value Pr(>F)
group  21  0.5328 0.9579
      836               
NULL

                        Df Sum Sq Mean Sq F value Pr(>F)    
Intervention             1   2840    2840   3.700 0.0548 .  
Timepoint               10 107893   10789  14.055 <2e-16 ***
Intervention:Timepoint  10   1056     106   0.138 0.9993    
Residuals              836 641764     768                   
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Independence of residuals: TRUE 

8.2 linear mixed model and assumptions

And let’s try linear mixed model instead where we account for participants, as well as assumptions

Show the code
S7_lmer_model <- lmer(Measurement ~ Timepoint * Intervention + (1|Participant), data = S7_subset_data)

anova(S7_lmer_model)
Type III Analysis of Variance Table with Satterthwaite's method
                       Sum Sq Mean Sq NumDF DenDF F value    Pr(>F)    
Timepoint              107893 10789.3    10   798 32.0034 < 2.2e-16 ***
Intervention             2840  2840.0     1   798  8.4241  0.003805 ** 
Timepoint:Intervention   1056   105.6    10   798  0.3132  0.977899    
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Show the code
check_model(S7_lmer_model)

9 Q8

Question 8.

Show the code
# create mean +- SD table for HUEL and Cornflakes S1, 0 to 240 minutes


result_S8 <- calculate_mean_sd(Satiety_long, question = "S8")

kable(result_S1)
Timepoint Mean_Cornflakes Mean_HUEL SD_Cornflakes SD_HUEL
0 62.3 60.5 20.0 21.9
15 26.3 21.5 22.4 21.4
30 31.1 18.7 26.1 17.2
45 31.6 21.4 24.1 19.4
60 34.7 24.3 24.0 19.9
90 37.8 28.9 22.5 21.8
120 45.2 34.9 23.2 22.6
150 52.5 40.3 22.3 23.4
180 60.0 51.0 21.7 25.0
210 65.5 56.3 20.0 25.6
240 72.4 63.8 18.2 22.0
Show the code
plot <- plot_mean_sd(result_S8)

print(plot)

First subset the question:

Show the code
#Subset the question

S8_subset_data <- subset_data(Satiety_long, "S8")

9.1 2 Way ANOVA and Checking the assumptions

Then a 2 way ANOVA and assumptions

Show the code
#| layout-ncol: 2

S8_anova_results_with_plots <- two_way_anova_with_plots(S8_subset_data)
Levene's Test for Homogeneity of Variance (center = median)
       Df F value Pr(>F)
group  21  0.7087  0.827
      836               
NULL

                        Df Sum Sq Mean Sq F value   Pr(>F)    
Intervention             1    630   629.6   0.711 0.399268    
Timepoint               10  28694  2869.4   3.241 0.000408 ***
Intervention:Timepoint  10    738    73.8   0.083 0.999924    
Residuals              836 740059   885.2                     
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Independence of residuals: TRUE 

9.2 linear mixed model and assumptions

And let’s try linear mixed model instead where we account for participants, as well as assumptions

Show the code
S8_lmer_model <- lmer(Measurement ~ Timepoint * Intervention + (1|Participant), data = S8_subset_data)

anova(S8_lmer_model)
Type III Analysis of Variance Table with Satterthwaite's method
                        Sum Sq Mean Sq NumDF DenDF F value  Pr(>F)    
Timepoint              28694.3 2869.43    10   798 14.0461 < 2e-16 ***
Intervention             629.6  629.63     1   798  3.0821 0.07954 .  
Timepoint:Intervention   737.9   73.79    10   798  0.3612 0.96280    
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Show the code
check_model(S8_lmer_model)